package com.jf.net.utils;

import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
 * SSLSocketFactoryUtil
 * @author JackyFlame
 * @time 2023/10/20 15:09
 * @description 生成SSL证书工具类
 */
public class SSLFactoryUtil {
    private static final String TAG = "SSLSocketFactoryUtil";
    private static final String PROTOCOL_TLS = "TLS";
    private static final String TYPE_X_509 = "X.509";
    private static final String TYPE_BKS = "bks";

    /**
     * 根据路径配置ssl证书(asset文件证书)
     * @param csRootCertificate root证书
     * @param httpsCertificate https证书
     * @param httpsPrivateKey 证书key
     * @return Pair<SSLSocketFactory, X509TrustManager>
     */
    public static Pair<SSLSocketFactory, X509TrustManager> getSSLSocketFactory(String csRootCertificate, String httpsCertificate, String httpsPrivateKey) {
        try (
                InputStream csRootIn = TextUtils.isEmpty(csRootCertificate) ? null : AppUtil.getInputStreamOfAssets(csRootCertificate);
                InputStream httpsCerIn = TextUtils.isEmpty(httpsCertificate) ? null : AppUtil.getInputStreamOfAssets(httpsCertificate);
        ) {
            InputStream[] inputStreamArr = (csRootIn == null) ? new InputStream[]{} : new InputStream[]{csRootIn};
            return getSslSocketFactoryInner(inputStreamArr, httpsCerIn, httpsPrivateKey);
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
            return null;
        }
    }

/*    *//**
     * 车机证书获取工具函数(车机内置文件证书)
     * @param csRootCertificate root证书
     * @param httpsCertificate https证书
     * @param httpsPrivateKey 证书key
     * @return Pair<SSLSocketFactory, X509TrustManager>
     * */
    public static Pair<SSLSocketFactory, X509TrustManager> getSSLSocketFactoryHu(String csRootCertificate, String httpsCertificate, String httpsPrivateKey) {
        try(FileInputStream csRootIn = TextUtils.isEmpty(csRootCertificate) ? null : new FileInputStream(csRootCertificate);
            FileInputStream httpsCerIn = TextUtils.isEmpty(httpsCertificate) ? null : new FileInputStream(httpsCertificate)
        ){
            InputStream[] inputStreamArr = (csRootIn == null) ? new InputStream[]{} : new InputStream[]{csRootIn};
            return getSslSocketFactoryInner(inputStreamArr, httpsCerIn, httpsPrivateKey);
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
            return null;
        }
    }

    private static Pair<SSLSocketFactory, X509TrustManager> getSslSocketFactoryInner(InputStream[] inputStreamArr, InputStream inputStream, String str) {
        try {
            TrustManager[] prepareTrustManager = prepareTrustManager(inputStreamArr);
            KeyManager[] prepareKeyManager = prepareKeyManager(inputStream, str);
            SSLContext instance = SSLContext.getInstance(PROTOCOL_TLS);
            X509TrustManager myTrustManager = chooseTrustManager(prepareTrustManager);
            instance.init(prepareKeyManager, new TrustManager[]{myTrustManager}, null);
            return new Pair<>(instance.getSocketFactory(), myTrustManager);
        } catch (Throwable e) {
            Log.e(TAG, e.getMessage());
            return null;
        }
    }

    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagerArr) {
        if (trustManagerArr != null) {
            for (TrustManager trustManager : trustManagerArr) {
                if (trustManager instanceof X509TrustManager) {
                    return (X509TrustManager) trustManager;
                }
            }
        }
        return null;
    }

    private static TrustManager[] prepareTrustManager(InputStream[] inputStreamArr) {
        try {
            CertificateFactory instance = CertificateFactory.getInstance(TYPE_X_509);
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            if (inputStreamArr != null && inputStreamArr.length > 0) {
                for (int i = 0; i < inputStreamArr.length; ++i) {
                    keyStore.setCertificateEntry(Integer.toString(i),
                            instance.generateCertificate(inputStreamArr[i]));
                }
            }
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            return trustManagerFactory.getTrustManagers();
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }

        return null;
    }

    private static KeyManager[] prepareKeyManager(InputStream inputStream, String str) {
        if (inputStream != null && str != null) {
            try {
                KeyStore instance = KeyStore.getInstance(TYPE_BKS);
                instance.load(inputStream, str.toCharArray());
                instance.getCertificateChain("alias");
                KeyManagerFactory instance2 = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                instance2.init(instance, str.toCharArray());
                return instance2.getKeyManagers();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static X509TrustManager getX509TrustManager(TrustManager[] tm) {
        for (TrustManager manager : tm) {
            if (manager instanceof X509TrustManager) {
                return (X509TrustManager) manager;
            }
        }
        return null;
    }
}
